﻿#region Header
// Copyright 2007-2011, Jerónimo Milea
// 
// This file is part of NetJsWire.
// 
//     NetJsWire is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
// 
//     NetJsWire is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
// 
//     You should have received a copy of the GNU General Public License
//     along with NetJsWire.  If not, see <http://www.gnu.org/licenses/>.
#endregion

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using NetJsWire.JsonRpcHandler;
using NetJsWire.Util;
using NetJsWire.Widgets.Core;
using NetJsWire.Widgets.Data;
using NetJsWire.Widgets.Ui.Layout;
using NetJsWire.Widgets.Ui.List;
using Newtonsoft.Json;
using ToolBar = NetJsWire.Widgets.Ui.ToolBar.ToolBar;

namespace NetJsWire.Widgets.Config
{
    [Serializable]
    [DisplayName( "Config options" )]
    [TypeConverter( typeof( ExpandableObjectConverter ) ), TypeDescriptionProvider( typeof( ConfigOptionsPropertys ) )]
    public class ObservableConfigOptions : IConfigOptions
    {
        protected readonly IWidget OwnerWidget;

        /// <summary>
        ///   Default constructor
        /// </summary>
        /// <param name = "ownerWidget">The owner of this configuration</param>
        public ObservableConfigOptions( IWidget ownerWidget )
        {
            OwnerWidget = ownerWidget;
        }

        protected void SetValue( string propName, object value, object defaultValue, object currValue )
        {
            if ( OwnerWidget.Renderer.Rendered )
                return;

            if ( value != defaultValue && !( defaultValue == null && value is string && string.IsNullOrEmpty( value as string ) ) )
            {
                if ( value is Enum )
                    OwnerWidget.Renderer.SetConstructionProperty( propName, value.ToString().ToLower() );
                else
                    OwnerWidget.Renderer.SetConstructionProperty( propName, value );
            }
            else if ( ( value == defaultValue && value != currValue ) || ( defaultValue == null && value is string && string.IsNullOrEmpty( value as string ) ) ) // we only remove the value if it was added here
            {
                OwnerWidget.Renderer.RemoveConstructionProperty( propName );
            }
        }

        public bool ShouldSerializeListeners()
        {
            return Listeners != null && Listeners.Count > 0;
        }

        #region Implementation of IConfigOptions

        /// <summary>
        ///   Specify true or specify a configuration object for Ext.list.ListView.ColumnResizer to enable the columns to be resizable (defaults to true).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual object ColumnResize { get; set; }

        /// <summary>
        ///   Specify true or specify a configuration object for Ext.list.ListView.Sorter to enable the columns to be sortable (defaults to true).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual object ColumnSort { get; set; }

        /// <summary>
        ///   An array of column configuration objects.
        /// </summary>
        /// <example>
        ///   {
        ///   align: 'right',
        ///   dataIndex: 'size',
        ///   header: 'Size',
        ///   tpl: '{size:fileSize}',
        ///   width: .35
        ///   }
        /// </example>
        /// <remarks>
        ///   Acceptable properties for each column configuration object are:
        ///   align : String
        ///   Set the CSS text-align property of the column. Defaults to 'left'.
        ///   dataIndex : String
        ///   See Ext.grid.Column. dataIndex for details.
        ///   header : String
        ///   See Ext.grid.Column. header for details.
        /// </remarks>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual ListViewColumnCollection Columns { get; set; }

        /// <summary>
        ///   <b>Note:</b> this config is only used when this Component is rendered by a Container which has been configured to use an AnchorLayout based layout manager, for example:
        ///   Ext.form.FormPanel
        ///   specifying layout: 'anchor' // or 'form', or 'absolute'
        ///   See Ext.layout.AnchorLayout.anchor also.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Anchor { get; set; }

        /// <summary>
        ///   Specify the id of the element, a DOM element or an existing Element corresponding to a DIV that is already present in the document that specifies some structural markup for this component.
        ///   Description :
        ///   When applyTo is used, constituent parts of the component can also be specified by id or CSS class name within the main element, and the component being created may attempt to create its subcomponents from that markup if applicable.
        ///   Notes :
        ///   When using this config, a call to render() is not required.
        ///   If applyTo is specified, any value passed for renderTo will be ignored and the target element's parent node will automatically be used as the component's container.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string ApplyTo { get; set; }

        /// <summary>
        ///   A tag name or DomHelper spec used to create the Element which will encapsulate this Component.
        ///   You do not normally need to specify this. For the base classes Ext.Component, Ext.BoxComponent, and Ext.Container, this defaults to 'div'. The more complex Ext classes use a more complex DOM structure created by their own onRender methods.
        ///   This is intended to allow the developer to create application-specific utility Components encapsulated by different DOM elements. Example usage:
        ///   {
        ///   xtype: 'box',
        ///   autoEl: {
        ///   tag: 'img',
        ///   src: 'http://www.example.com/example.jpg'
        ///   }
        ///   }, {
        ///   xtype: 'box',
        ///   autoEl: {
        ///   tag: 'blockquote',
        ///   html: 'autoEl is cool!'
        ///   }
        ///   }, {
        ///   xtype: 'container',
        ///   autoEl: 'ul',
        ///   cls: 'ux-unordered-list',
        ///   items: {
        ///   xtype: 'box',
        ///   autoEl: 'li',
        ///   html: 'First list item'
        ///   }
        ///   }
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string AutoEl { get; set; }

        /// <summary>
        ///   True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove them on render (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool AutoShow { get; set; }

        /// <summary>
        ///   CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string DisabledClass { get; set; }

        /// <summary>
        ///   <b>Note: this config is only used when this Component is rendered by a Container which has been configured to use a BoxLayout.</b>
        ///   Each child Component with a flex property will be flexed either vertically (by a VBoxLayout) or horizontally (by an HBoxLayout) according to the item's relative flex value compared to the sum of all Components with flex value specified. Any child items that have either a flex = 0 or flex = undefined will not be 'flexed' (the initial size will not be changed).
        /// </summary>
        [Description( "Each child Component with a flex property will be flexed either vertically (by a VBoxLayout) or horizontally (by an HBoxLayout) according to the item's relative flex value compared to the sum of all Components with flex value specified." )]
        [DefaultValue( 0D )]
        [Browsable( false )]
        public virtual double Flex { get; set; }

        /// <summary>
        ///   The label text to display next to this Component (defaults to '').
        ///   <remarks>
        ///     Note: this config is only used when this Component is rendered by a Container which has been configured to use the FormLayout layout manager (e.g. Ext.form.FormPanel or specifying layout:'form').
        ///     Also see hideLabel and Ext.layout.FormLayout.fieldTpl.
        ///   </remarks>
        ///   <example>
        ///     Example use:
        ///     <code>
        ///       new Ext.FormPanel({
        ///       height: 100,
        ///       renderTo: Ext.getBody(),
        ///       items: [{
        ///       xtype: 'textfield',
        ///       fieldLabel: 'Name'
        ///       }]
        ///       });
        ///     </code>
        ///   </example>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string FieldLabel { get; set; }

        /// <summary>
        ///   The CSS class used to to apply to the special clearing div rendered directly after each form field wrapper to provide field clearing (defaults to 'x-form-clear-left').
        ///   <remarks>
        ///     Note: this config is only used when this Component is rendered by a Container which has been configured to use the FormLayout layout manager 
        ///     (e.g. Ext.form.FormPanel or specifying layout:'form') and either a fieldLabel is specified or isFormField=true is specified.
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string ClearCls { get; set; }

        /// <summary>
        ///   An optional extra CSS class that will be added to this component's Element (defaults to ''). 
        ///   This can be useful for adding customized styles to the component or any of its children using standard CSS rules.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Cls { get; set; }

        /// <summary>
        ///   An HTML fragment, or a DomHelper specification to use as the layout element content (defaults to '').
        ///   The HTML content is added after the component is rendered, so the document will not contain this HTML at the time the render event is fired. This content is inserted into the body before any configured contentEl is appended.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Html { get; set; }

        /// <summary>
        ///   An additional CSS class to apply to the div wrapping the form item element of this field. If supplied, itemCls at the field level will override the default itemCls supplied at the container level. The value specified for itemCls will be added to the default class ('x-form-item').
        ///   Since it is applied to the item wrapper (see Ext.layout.FormLayout.fieldTpl), it allows you to write standard CSS rules that can apply to the field, the label (if specified), or any other element within the markup for the field.
        ///   <remarks>
        ///     This config is only used when this Component is rendered by a Container which has been configured to use the FormLayout layout manager (e.g. Ext.form.FormPanel or specifying layout:'form').
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string ItemCls { get; set; }

        /// <summary>
        ///   The layout type to be used for this container.
        ///   <remarks>
        ///     *Important: In order for child items to be correctly sized and positioned, typically a layout manager must be specified through the layout configuration option.
        ///   </remarks>
        ///   The sizing and positioning of child items is the responsibility of the Container's layout manager which creates and manages the type of layout you have in mind.
        ///   For example:
        ///   <example>
        ///     <code>
        ///       new Ext.Window({
        ///       width:300, height: 300,
        ///       layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
        ///       items: [{
        ///       title: 'Panel inside a Window'
        ///       }]
        ///       }).show();
        ///     </code>
        ///   </example>
        ///   If the layout configuration is not explicitly specified for a general purpose container (e.g. Container or Panel) the default layout manager will be used 
        ///   which does nothing but render child components sequentially into the Container (no sizing or positioning will be performed in this situation).
        ///   Some container classes implicitly specify a default layout (e.g. FormPanel specifies layout:'form'). Other specific purpose classes internally 
        ///   specify/manage their internal layout (e.g. GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( LayoutType ) 0 )]
        public virtual LayoutType Layout { get; set; }

        /// <summary>
        ///   This is a config object containing properties specific to the chosen <see cref = "IConfigOptions.Layout" /> if <see cref = "IConfigOptions.Layout" /> has been specified as a string.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string LayoutConfig { get; set; }

        /// <summary>
        ///   An array of events that, when fired, should trigger this component to save its state (defaults to none).
        ///   <remarks>
        ///     stateEvents may be any type of event supported by this component, including browser or custom events (e.g., ['click', 'customerchange']).
        ///   </remarks>
        ///   See <see cref = "IConfigOptions.StateFul" /> for an explanation of saving and restoring Component state.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string StateEvents { get; set; }

        /// <summary>
        ///   The unique id for this component to use for state management purposes (defaults to the component id if one was set, otherwise null if the component is using a generated id).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string StateId { get; set; }

        /// <summary>
        ///   A flag which causes the Component to attempt to restore the state of internal properties from a saved state on startup.
        ///   The component must have either a stateId or id assigned for state to be managed. Auto-generated ids are not guaranteed to be stable across page loads and cannot be relied upon to save and restore the same state for a component.
        ///   <remarks>
        ///     For state saving to work, the state manager's provider must have been set to an implementation of Ext.state.Provider which overrides the set and get methods to save and recall name/value pairs. A built-in implementation, Ext.state.CookieProvider is available.
        ///     To set the state provider for the current page:
        ///     <code>
        ///       Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
        ///       expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
        ///       }));
        ///     </code>
        ///     A stateful Component attempts to save state when one of the events listed in the stateEvents configuration fires.
        ///     To save state, a stateful Component first serializes its state by calling getState. By default, this function does nothing. The developer must provide an implementation which returns an object hash which represents the Component's restorable state.
        ///     The value yielded by getState is passed to Ext.state.Manager.set which uses the configured Ext.state.Provider to save the object keyed by the Component's stateId, or, if that is not specified, its id.
        ///     During construction, a stateful Component attempts to restore its state by calling Ext.state.Manager.get passing the stateId, or, if that is not specified, the id.
        ///     The resulting object is passed to applyState. The default implementation of applyState simply copies properties into the object, but a developer may override this to support more behaviour.
        ///     You can perform extra processing on state save and restore by attaching handlers to the beforestaterestore, staterestore, beforestatesave and statesave events.
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool StateFul { get; set; }

        /// <summary>
        ///   A custom style specification to be applied to this component's Element. Should be a valid argument to Ext.Element.applyStyles.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Style { get; set; }

        /// <summary>
        ///   An array of tool button configs to be added to the header tool area. When rendered, each tool is stored as an Element referenced by a public property called tools.&lt;tool-type&gt;.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        [Description( "An array of tool button configs to be added to the header tool area. When rendered, each tool is stored as an Element referenced by a public property called tools.&lt;tool-type&gt;." )]
        public virtual List<ToolConfig> Tools { get; set; }

        /// <summary>
        ///   An Ext.Template, Ext.XTemplate or an array of strings to form an Ext.XTemplate. Used in conjunction with the data and tplWriteMode configurations.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Tpl { get; set; }

        /// <summary>
        ///   The Ext.(X)Template method to use when updating the content area of the Component. Defaults to 'overwrite' (see Ext.XTemplate.overwrite).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string TplWriteMode { get; set; }

        /// <summary>
        ///   The registered xtype to create.
        ///   This config option is not used when passing a config object into a constructor.
        ///   This config option is used only when lazy instantiation is being used, and a child item of a Container is being specified not as a fully instantiated Component, but as a Component config object.
        ///   The xtype will be looked up at render time up to determine what type of child Component to create.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        [TypeConverter( typeof( XtypeStringConverter ) )]
        public virtual string Xtype { get; set; }

        /// <summary>
        ///   true to animate the transition when the panel is collapsed, false to skip the animation (defaults to true if the Ext.Fx class is available, otherwise false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool AnimCollapse { get; set; }

        /// <summary>
        ///   true to use height:'auto', false to use fixed height (defaults to false).
        ///   <remarks>
        ///     Although many components inherit this config option, not all will function as expected with a height of 'auto'. Setting autoHeight:true means 
        ///     that the browser will manage height based on the element's contents, and that Ext will not manage it at all.
        ///     If the browser is managing the height, be aware that resizes performed by the browser in response to changes within the structure of the 
        ///     Component cannot be detected. Therefore changes to the height might result in elements needing to be synchronized with the new height. Example:
        ///     <example>
        ///       <code>
        ///         var w = new Ext.Window({
        ///         title: 'Window',
        ///         width: 600,
        ///         autoHeight: true,
        ///         items: {
        ///         title: 'Collapse Me',
        ///         height: 400,
        ///         collapsible: true,
        ///         border: false,
        ///         listeners: {
        ///         beforecollapse: function() {
        ///         w.el.shadow.hide();
        ///         },
        ///         beforeexpand: function() {
        ///         w.el.shadow.hide();
        ///         },
        ///         collapse: function() {
        ///         w.syncShadow();
        ///         },
        ///         expand: function() {
        ///         w.syncShadow();
        ///         }
        ///         }
        ///         }
        ///         }).show();
        ///       </code>
        ///     </example>
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool AutoHeight { get; set; }

        /// <summary>
        ///   A valid url spec according to the Updater Ext.Updater.update method.
        ///   If autoLoad is not null, the panel will attempt to load its contents immediately upon render.
        ///   The URL will become the default URL for this panel's body element, so it may be refreshed at any time.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string AutoLoad { get; set; }

        /// <summary>
        ///   The base CSS class to apply to this panel's element (defaults to 'x-panel').
        ///   Another option available by default is to specify 'x-plain' which strips all styling except for required attributes for Ext layouts to function (e.g. overflow:hidden). 
        ///   See <see cref = "IConfigOptions.Unstyled" /> also.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string BaseCls { get; set; }

        /// <summary>
        ///   This can be a Ext.Toolbar object, a toolbar config, or an array of buttons/button configs to be added to the toolbar. Note that this is not available as a property after render.
        ///   To access the bottom toolbar after render, use getBottomToolbar.
        ///   <b>Note:</b> Although a Toolbar may contain Field components, these will not be updated by a load of an ancestor FormPanel. A Panel's toolbars are not part of the standard 
        ///   Container->Component hierarchy, and so are not scanned to collect form items. However, the values will be submitted because form submission parameters are collected from the DOM tree.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual ToolBar BottomBar { get; set; }

        /// <summary>
        ///   A DomHelper element specification object specifying the element structure of this Panel's bbar Element. See <see cref = "IConfigOptions.BodyCfg" /> also.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string BottomBarCfg { get; set; }

        /// <summary>
        ///   True to display an interior border on the body element of the panel, false to hide it (defaults to true).
        ///   This only applies when border == true. If border == true and bodyBorder == false, the border will display as a 1px wide inset border, giving the entire body element an inset appearance.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool BodyBorder { get; set; }

        /// <summary>
        ///   A DomHelper element specification object may be specified for any Panel Element.
        ///   By default, the Default element in the table below will be used for the html markup to create a child element with the commensurate Default class name (<see cref = "IConfigOptions.BaseCls" /> will be replaced by <see cref = "IConfigOptions.BaseCls" />):
        /// </summary>
        /// <remarks>
        ///   <table>
        ///     <theader>
        ///       <tr>
        ///         <td>Panel Element</td>
        ///         <td>Default Element</td>
        ///         <td>Default class</td>
        ///         <td>Custom Element</td>
        ///         <td>Additional class</td>
        ///         <td>Additional style</td>
        ///       </tr>
        ///     </theader>
        ///     <tbody>
        ///       <tr>
        ///         <td>header</td>
        ///         <td>div</td>
        ///         <td>baseCls+'-header'</td>
        ///         <td>headerCfg</td>
        ///         <td>headerCssClass</td>
        ///         <td>headerStyle</td>
        ///       </tr>
        ///       <tr>
        ///         <td>header</td>
        ///         <td>div</td>
        ///         <td>baseCls+'-bwrap'</td>
        ///         <td>bwrapCfg</td>
        ///         <td>bwrapCssClass</td>
        ///         <td>bwrapStyle</td>
        ///       </tr>
        ///       <tr>
        ///         <td>+ tbar</td>
        ///         <td>div</td>
        ///         <td>baseCls+'-tbar'</td>
        ///         <td>tbarCfg</td>
        ///         <td>tbarCssClass</td>
        ///         <td>tbarStyle</td>
        ///       </tr>
        ///       <tr>
        ///         <td>+ body</td>
        ///         <td>div</td>
        ///         <td>baseCls+'-body'</td>
        ///         <td>bodyCfg</td>
        ///         <td>bodyCssClass</td>
        ///         <td>bodyStyle</td>
        ///       </tr>
        ///       <tr>
        ///         <td>+ bbar</td>
        ///         <td>div</td>
        ///         <td>baseCls+'-bbar'</td>
        ///         <td>bbarCfg</td>
        ///         <td>bbarCssClass</td>
        ///         <td>bbarStyle</td>
        ///       </tr>
        ///       <tr>
        ///         <td>+ footer</td>
        ///         <td>div</td>
        ///         <td>baseCls+'-footer'</td>
        ///         <td>footerCfg</td>
        ///         <td>footerCssClass</td>
        ///         <td>footerStyle</td>
        ///       </tr>
        ///     </tbody>
        ///   </table>
        ///   <example>
        ///     Configuring a Custom element may be used, for example, to force the body Element to use a different form of markup than is created by default.
        ///     An example of this might be to create a child Panel containing a custom content, such as a header, or forcing centering of all Panel content by having the body be a &lt;center&gt; element:
        ///     <code>
        ///       new Ext.Panel({
        ///       title: 'Message Title',
        ///       renderTo: Ext.getBody(),
        ///       width: 200, height: 130,
        ///       bodyCfg: {
        ///       tag: 'center',
        ///       cls: 'x-panel-body',  // Default class not applied if Custom element specified
        ///       html: 'Message'
        ///       },
        ///       footerCfg: {
        ///       tag: 'h2',
        ///       cls: 'x-panel-footer'        // same as the Default class
        ///       html: 'footer html'
        ///       },
        ///       footerCssClass: 'custom-footer', // additional css class, see addClass
        ///       footerStyle:    'background-color:red' // see bodyStyle
        ///       });
        ///     </code>
        ///     The example above also explicitly creates a footer with custom markup and styling applied.
        ///   </example>
        /// </remarks>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string BodyCfg { get; set; }

        /// <summary>
        ///   Additional css class selector to be applied to the body element in the format expected by <c>Ext.Element.addClass</c> (defaults to null). See <see cref = "IConfigOptions.BodyCfg" />.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string BodyCssClass { get; set; }

        /// <summary>
        ///   Custom CSS styles to be applied to the body element in the format expected by <c>Ext.Element.applyStyles</c> (defaults to null). See <see cref = "IConfigOptions.BodyCfg" />.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string BodyStyle { get; set; }

        /// <summary>
        ///   True to display the borders of the panel's body element, false to hide them (defaults to true).
        ///   By default, the border is a 2px wide inset border, but this can be further altered by setting <see cref = "IConfigOptions.BodyBorder" /> to false.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool Border { get; set; }

        /// <summary>
        ///   The alignment of any buttons added to this panel.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( ButtonAlign ) 0 )]
        public virtual ButtonAlign ButtonAlign { get; set; }

        /// <summary>
        ///   A DomHelper element specification object specifying the element structure of this Panel's bwrap Element. See <see cref = "IConfigOptions.BodyCfg" /> also.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string BwrapCfg { get; set; }

        /// <summary>
        ///   Panels themselves do not directly support being closed, but some Panel subclasses do (like Ext.Window) or a Panel Class within an Ext.TabPanel. Specify true to enable closing in such situations. Defaults to false.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool Closable { get; set; }

        /// <summary>
        ///   true to make sure the collapse/expand toggle button always renders first (to the left of) any other tools in the panel's title bar, false to render it last (defaults to true).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool CollapseFirst { get; set; }

        /// <summary>
        ///   true to render the panel collapsed, false to render it expanded (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool Collapsed { get; set; }

        /// <summary>
        ///   True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into the header tool button area, false to keep the panel statically sized with no button (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool Collapsible { get; set; }

        /// <summary>
        ///   Overrides the <see cref = "IConfigOptions.BaseCls" /> setting to <see cref = "IConfigOptions.BaseCls" /><c> = 'x-plain'</c> which renders the panel unstyled except for required attributes for Ext layouts to function (e.g. <c>overflow:hidden</c>).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool Unstyled { get; set; }

        /// <summary>
        ///   true to use overflow:'auto' on the components layout element and show scroll bars automatically when necessary, false to clip any overflowing content (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool AutoScroll { get; set; }

        /// <summary>
        ///   True to use width:'auto', false to use fixed width (or allow it to be managed by its parent Container's layout manager. Defaults to false.
        ///   <remarks>
        ///     Although many components inherit this config option, not all will function as expected with a width of 'auto'. Setting autoWidth:true means 
        ///     that the browser will manage width based on the element's contents, and that Ext will not manage it at all.
        ///     If the browser is managing the width, be aware that resizes performed by the browser in response to changes within the structure of the Component 
        ///     cannot be detected. Therefore changes to the width might result in elements needing to be synchronized 
        ///     with the new width. For example, where the target element is:
        ///     <code>
        ///       <![CDATA[<div id='grid-container' style='margin-left:25%;width:50%'></div>]]>
        ///     </code>
        ///     A Panel rendered into that target element must listen for browser window resize in order to relay its child items when the browser changes its width:
        ///     <code>
        ///       var myPanel = new Ext.Panel({
        ///       renderTo: 'grid-container',
        ///       monitorResize: true, // relay on browser resize
        ///       title: 'Panel',
        ///       height: 400,
        ///       autoWidth: true,
        ///       layout: 'hbox',
        ///       layoutConfig: {
        ///       align: 'stretch'
        ///       },
        ///       defaults: {
        ///       flex: 1
        ///       },
        ///       items: [{
        ///       title: 'Box 1',
        ///       }, {
        ///       title: 'Box 2'
        ///       }, {
        ///       title: 'Box 3'
        ///       }],
        ///       });
        ///     </code>
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool AutoWidth { get; set; }

        /// <summary>
        ///   The maximum value in pixels which this BoxComponent will set its height to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual int? BoxMaxHeight { get; set; }

        /// <summary>
        ///   The maximum value in pixels which this BoxComponent will set its width to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual int? BoxMaxWidth { get; set; }

        /// <summary>
        ///   The minimum value in pixels which this BoxComponent will set its height to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual int? BoxMinHeight { get; set; }

        /// <summary>
        ///   The minimum value in pixels which this BoxComponent will set its width to.
        ///   <remarks>
        ///     Warning: This will override any size management applied by layout managers.
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual int? BoxMinWidth { get; set; }

        /// <summary>
        ///   An object containing margins to apply to this BoxComponent in the format:
        ///   <remarks>
        ///     this config is only used when this BoxComponent is rendered by a Container which has been configured to use the 
        ///     BorderLayout or one of the two BoxLayout subclasses.
        ///   </remarks>
        ///   E.g.:
        ///   <code>
        ///     {
        ///     top: (top margin),
        ///     right: (right margin),
        ///     bottom: (bottom margin),
        ///     left: (left margin)
        ///     }
        ///   </code>
        ///   May also be a string containing space-separated, numeric margin values. The order of the sides associated with each value matches the way CSS processes margin values:
        ///   <list type = "bullet">
        ///     <item>
        ///       If there is only one value, it applies to all sides.
        ///     </item>
        ///     <item>
        ///       If there are two values, the top and bottom borders are set to the first value and the right and left are set to the second.
        ///     </item>
        ///     <item>
        ///       If there are three values, the top is set to the first value, the left and right are set to the second, and the bottom is set to the third.
        ///     </item>
        ///     <item>
        ///       If there are four values, they apply to the top, right, bottom, and left, respectively.
        ///     </item>
        ///   </list>
        ///   Defaults to:
        ///   <code>
        ///     {top:0, right:0, bottom:0, left:0}
        ///   </code>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual Padding Margins { get; set; }

        /// <summary>
        ///   An object or array of objects that will provide custom functionality for this component.
        ///   The only requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
        ///   When a component is created, if any plugins are available, the component will call the init method on each plugin, passing a reference to itself.
        ///   Each plugin can then call methods or respond to events on the component as needed to provide its functionality.
        /// </summary>
        [Description( "An object or array of objects that will provide custom functionality for this component." )]
        [DefaultValue( null )]
        [Browsable( false )]
        public virtual List<object> Plugins { get; private set; }

        /// <summary>
        ///   The region this Component represents in a BorderLayout.
        ///   <remarks>
        ///     This config is only used when this BoxComponent is rendered by a Container which has been configured to use the BorderLayout layout manager 
        ///     (e.g. specifying layout:'border').
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Region { get; set; }

        /// <summary>
        ///   A string component id or the numeric index of the component that should be initially activated within the container's layout on render. 
        ///   For example, <c>activeItem: 'item-1'</c> or <c>activeItem: 0</c> (index 0 = the first item in the container's collection).
        ///   <remarks>
        ///     activeItem only applies to layout styles that can display items one at a time (like Ext.layout.AccordionLayout, Ext.layout.CardLayout and 
        ///     Ext.layout.FitLayout). Related to Ext.layout.ContainerLayout.activeItem.
        ///   </remarks>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual object ActiveItem { get; set; }

        /// <summary>
        ///   If true the container will automatically destroy any contained component that is removed from it, else destruction must be handled manually (defaults to true).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool AutoDestroy { get; set; }

        /// <summary>
        ///   An array of events that, when fired, should be bubbled to any parent container.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string BubbleEvents { get; set; }

        /// <summary>
        ///   When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer the frequency it calculates and does a re-layout of components.
        ///   This is useful for heavy containers or containers with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to 50.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual int? BufferResize { get; set; }

        /// <summary>
        ///   This option is a means of applying default settings to all added items whether added through the items config or via the add or insert methods.
        ///   If an added item is a config object, and not an instantiated Component, then the default properties are unconditionally applied. If the added item
        ///   is an instantiated Component, then the default properties are applied conditionally so as not to override existing properties in the item.
        ///   If the defaults option is specified as a function, then the function will be called using this Container as the scope (this reference) and passing 
        ///   the added item as the first parameter. Any resulting object from that call is then applied to the item as default properties.
        ///   For example, to automatically apply padding to the body of each of a set of contained Ext.Panel items, you could pass: <c>defaults: {bodyStyle:'padding:15px'}.</c>
        ///   <example>
        ///     <code>
        ///       defaults: {               // defaults are applied to items, not the container
        ///       autoScroll:true
        ///       },
        ///       items: [
        ///       {
        ///       xtype: 'panel',   // defaults do not have precedence over
        ///       id: 'panel1',     // options in config objects, so the defaults
        ///       autoScroll: false // will not be applied here, panel1 will be autoScroll:false
        ///       },
        ///       new Ext.Panel({       // defaults do have precedence over options
        ///       id: 'panel2',     // options in components, so the defaults
        ///       autoScroll: false // will be applied here, panel2 will be autoScroll:true.
        ///       })
        ///       ]
        ///     </code>
        ///   </example>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Defaults { get; set; }

        /// <summary>
        ///   If true the container will force a layout initially even if hidden or collapsed.
        ///   This option is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool ForceLayout { get; set; }

        /// <summary>
        ///   True to hide the borders of each contained component, false to defer to the component's existing border settings (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool HideBorders { get; set; }

        /// <summary>
        ///   True to automatically monitor window resize events to handle anything that is sensitive to the current size of the viewport.
        ///   <i>This value is typically managed by the chosen layout and should not need to be set manually.</i>
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual bool? MonitorResize { get; set; }

        /// <summary>
        ///   The event to listen to for resizing in layouts. Defaults to 'resize'.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string ResizeEvent { get; set; }

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool AutoSave { get; set; }

        [Browsable( false )]
        [DefaultValue( null )]
        public virtual List<BaseParam> BaseParams { get; set; }

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool Batch { get; set; }

        [Browsable( false )]
        [DefaultValue( null )]
        public virtual ParamNames DefaultParamNames { get; set; }

        [Browsable( false )]
        [DefaultValue( null )]
        public virtual ParamNames ParamNames { get; set; }

        [Browsable( false )]
        [DefaultValue( null )]
        public virtual DataProxy Proxy { get; set; }

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool PruneModifiedRecords { get; set; }

        [Browsable( false )]
        [DefaultValue( null )]
        public virtual DataReader Reader { get; set; }

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool RemoteSort { get; set; }

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool RestFul { get; set; }

        [Browsable( false )]
        [DefaultValue( null )]
        public virtual SortInfo SortInfo { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string StoreId { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Url { get; set; }

        [Browsable( false )]
        [DefaultValue( null )]
        public virtual DataWriter Writer { get; set; }

        [Browsable( false )]
        [DefaultValue( 0 )]
        public virtual int IdIndex { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string IdProperty { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Root { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string SuccessProperty { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string TotalProperty { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string FieldClass { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string FocusClass { get; set; }

        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string Name { get; set; }

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool Shadow { get; set; }

        #endregion

        #region TabPanel

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool DeferredRender { get; set; }

        #endregion

        #region DataView

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool BlockRefresh { get; set; }

        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool DeferEmptyText { get; set; }

        /// <summary>
        ///   The text to display in the view when there is no data to display (defaults to '').
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string EmptyText { get; set; }

        /// <summary>
        ///   This is a required setting. A simple CSS selector (e.g. div.some-class or span:first-child) that will be used to determine what nodes this DataView will be working with.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string ItemSelector { get; set; }

        /// <summary>
        ///   A string to display during data load operations (defaults to undefined).
        ///   If specified, this text will be displayed in a loading div and the view's contents will be cleared while loading, otherwise the view's contents will continue to display normally until the new data is loaded and the contents are replaced.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string LoadingText { get; set; }

        /// <summary>
        ///   True to allow selection of more than one item at a time, false to allow selection of only a single item at a time or no selection at all, depending on the value of singleSelect (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool MultiSelect { get; set; }

        /// <summary>
        ///   A CSS class to apply to each item in the view on mouseover (defaults to undefined).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string OverClass { get; set; }

        /// <summary>
        ///   A CSS class to apply to each selected item in the view (defaults to 'x-view-selected').
        /// </summary>
        [Browsable( false )]
        [DefaultValue( ( string ) null )]
        public virtual string SelectedClass { get; set; }

        /// <summary>
        ///   True to enable multiselection by clicking on multiple items without requiring the user to hold Shift or Ctrl, false to force the user to hold Ctrl or Shift to select more than on item (defaults to false).
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool SimpleSelect { get; set; }

        /// <summary>
        ///   True to allow selection of exactly one item at a time, false to allow no selection at all (defaults to false).
        /// </summary>
        /// <remarks>
        ///   Note that if multiSelect = true, this value will be ignored.
        /// </remarks>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool SingleSelect { get; set; }

        /// <summary>
        ///   The Ext.data.Store to bind this DataView to.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( null )]
        public virtual IDataStore Store { get; set; }

        /// <summary>
        ///   True to enable mouseenter and mouseleave events.
        /// </summary>
        [Browsable( false )]
        [DefaultValue( false )]
        public virtual bool TrackOver { get; set; }

        #endregion

        #region Implemented

        private List<Listener> _listeners = new List<Listener>();

        /// <summary>
        ///   A config object containing one or more event handlers to be added to this object during initialization.<br />
        ///   While some ExtJs Component classes export selected DOM events (e.g. "click", "mouseover" etc), this is usually only done when extra value can be added. 
        ///   For example the DataView's click event passing the node clicked on. 
        ///   To access DOM events directly from a Component's HTMLElement, listeners must be added to the Element after the Component has been rendered.
        /// </summary>
        [Description( "A config object containing one or more event handlers to be added to this object during initialization." )]
        [DesignerSerializationVisibility( DesignerSerializationVisibility.Content )]
        [JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, ObjectCreationHandling = ObjectCreationHandling.Reuse )]
        [Browsable( true )]
        public virtual List<Listener> Listeners
        {
            get { return _listeners; }
            set
            {
                SetValue( "listeners", value, null, _listeners );
                _listeners = value;
            }
        }

        #endregion
    }
}
